#
#  <Test>
#    <TestType>DRT</TestType>
#    <Summary>Verifies the New-PsSpecProject cmdlet</Summary>
#  </Test>
##
## Test case goals:
##
## - Create new valid noun (Name, Definition) (New-PsSpecNoun cmdlet)
## - Try to create a noun that exists
## - Try to create a noun with invalid characters
## - Create a cmdlet (support Project, Snapin, Verb, Noun)
## - Create a cmdlet, warn for duplicate Verb and Noun
## - Create a cmdlet, error for duplicate Project, Verb, and Noun
## - Create a cmdlet with non-existent verb (error)
## - Create a cmdlet with non-existent noun (error)
## - Owner can create / edit a cmdlet (New-PsSpecCmdlet cmdlet)
## - Cmdlet author can create / edit a cmdlet
## - Random user cannot create / edit a cmdlet
## - Update short description (Update-ShortDescription)
## - Update long description (Update-LongDescription)
## - Update ShouldProcess (Update-ShouldProcess)
## - Update InputObject (type / description) (Add-InputObject / Update-InputObject / Remove-InputObject)
## - Update OutputObject (type / scenario) (Add-OutputObject / Update-OutputObject / Remove-OutputObject)
## - Add parameter (more spec required) (Add-PsSpecCmdletParemeter / Set-PsSpecCmdletParameter / Remove-PsSpecCmdletParameter)
## - Delete parameter
## - Update parameter

## - Update Role
## - Update Category
## - Update System Requirements
## - Update Security issues
## - Update Related to
## - Update Remoting issues
## - Update Assembly name

##
. (join-path $args[0] "..\Asserts.ps1")

Add-PsSnapin PsSpecCmdletManagement -ErrorAction SilentlyContinue
$testService = "http://localhost/cmdletdesigner/cmdlet.asmx"
$testDatasource = ".\SQLEXPRESS"
$testDatabase = "AspenManagement"
$username = "$env:USERDOMAIN\$env:USERNAME"
$sqlCommand = Resolve-Path (Join-Path $args[0] "Scripts\Invoke-SqlCommand.ps1")

$error.Clear()
function AssertArrayEquals
{
    param($expectedArray, $resultArray, $message)

    for($counter = 0; $counter -lt $expectedArray.Count; $counter++)
    {
        AssertEquals $expectedArray[$counter] $resultArray[$counter] ("$message #$counter. Expected {0}, Got {1}" -f $expectedArray[$counter],$resultArray[$counter])
    }
}

## Function to clear spec history
function ClearSpecHistory
{
    $clearSpecHistorySql = "DELETE FROM SpecHistory"
    [void] (& $sqlCommand $testDataSource $testDatabase $clearSpecHistorySql)
}

## Remove old test data
Get-PsSpecProject "TestProject*" -Service $testService | Remove-PsSpecProject -Service $testService -Force
AssertEquals 0 @(Get-PsSpecProject "TestProject*" -Service $testService).Count "Should have a fresh slate."

ClearSpecHistory

## Create new data
$project = New-PsSpecProject "TestProject" "This is a description of my project" -Service $testService

## Verify that you can not specify alternate change types
$error.Clear()
$oldErrorAction = $errorActionPreference
$errorActionPreference = "SilentlyContinue"
$project | Get-PsSpecHistory -ChangeType Noun -Service $testService
$project | Get-PsSpecHistory -ChangeType CmdletParameter -Service $testService
$project | Get-PsSpecHistory -ChangeType ParameterSetEntry -Service $testService
AssertEquals 3 $error.Count "Should not be able to specify other change types"
$errorActionPreference = $oldErrorAction
$error.Clear()

## Verify that the history was updated
$history = @($project | Get-PsSpecHistory -ChangeType Project -Service $testService | ? { $_.ChangeType -eq "Project" } )[0]
AssertEquals "TestProject" $history.NewValue "Should have created project history"


$existingProjectSql = @"
    DELETE FROM VerbException

    -- Create a test project
    EXEC NewProject 'TestProjectExistingProject','An Existing Project','$username'
    EXEC NewProject 'TestProjectExistingDependentProject','An Existing Project','SECRETDOMAIN\dependentUser'

    EXEC NewNoun 'DuplicateNoun','DuplicateNounDescription2','TestProjectExistingProject','$username'
    EXEC NewNoun 'RestrictedNoun','RestrictedNounDescription','TestProjectExistingProject','$username'

    -- And some nouns
    DECLARE @projectId INT
    SET @projectId = (SELECT ProjectId FROM Project
                                      WHERE Name = 'TestProjectExistingProject')
    INSERT INTO dbo.Noun (Name, Definition, ProjectId, Type)
           VALUES ('SharedNoun', 'This is a shared noun', @projectId, 1)
    INSERT INTO dbo.Noun (Name, Definition, ProjectId, Type)
           VALUES ('CommonNoun', 'This is a common noun', @projectId, 2)
    INSERT INTO dbo.Noun (Name, Definition, ProjectId, Type)
           VALUES ('SharedDependentNoun', 'This is a shared dependent noun that somebody will depend on', @projectId, 1)

    -- And some cmdlets
    EXEC NewCmdlet @snapin='FooSnapin',@verb='Get',@noun='SharedNoun',@project='TestProjectExistingProject',@shortDescription='Get a shared noun',@longDescription='Get a shared noun long desc.',@supportsShouldProcess=1,@notes='Some notes',@user='$username'

    -- Add a restricted verb to another project
    INSERT INTO dbo.VerbException (Name, ProjectId)
        VALUES ('Grant', 99999)
"@

## Create existing project
[void] (& $sqlCommand $testDataSource $testDatabase $existingProjectSql)

ClearSpecHistory

## Simple add noun
[void] (New-PsSpecNoun TestNoun TestNounDescription TestProject -Service $testService)
$nouns = @(Get-PsSpecNoun "TestNoun" -Service $testService)
AssertEquals 1 $nouns.Count "Should have created noun"
$noun = $nouns[0]
Assert ($noun.Id -gt 0) "Nouns should have an id"
AssertEquals "TestNoun" $noun.Name
AssertEquals "TestNounDescription" $noun.Definition
AssertEquals "TestProject" $noun.ProjectName

## Verify that the history was updated
$project = Get-PsSpecProject TestProject -Service $testService
$history = @($project | Get-PsSpecHistory -ChangeType Project -Service $testService | ? { $_.ChangeType -eq "Project" } )[0]
AssertEquals "TestNoun" $history.Notes "Should have created noun history"

## Check that we can get it, even though it has no cmdlets
$nouns = @(Get-PsSpecNoun -ProjectName TestProject -Service $testService)
AssertEquals 1 $nouns.Count "Should have created noun"
$noun = $nouns[0]
AssertEquals "TestNoun" $noun.Name
AssertEquals "TestNounDescription" $noun.Definition
AssertEquals "TestProject" $noun.ProjectName

## Cannot add duplicate noun
[void] (New-PsSpecNoun TestNoun TestNounDescription TestProject -Service $testService -ErrorAction SilentlyContinue)
AssertEquals 1 $error.Count "Should not be able to create a new noun with the same name"
$error.Clear()

## Add long description
$testNoun = New-PsSpecNoun "TestNounTwo" ("A"*200) TestProject -Service $testService
$nouns = @(Get-PsSpecNoun "TestNounTwo" -Service $testService)
AssertEquals 1 $nouns.Count "Should have created noun with long description"
AssertEquals "TestNounTwo" $testNoun.Name
AssertEquals ("A"*200) $testNoun.Definition

## Check for invalid characters in the name
[void] (New-PsSpecNoun "Test Noun" TestNounDescription TestProject -Service $testService -ErrorAction SilentlyContinue)
AssertEquals 1 $error.Count "Should not be able to create a new project with invalid characters 1"
$error.Clear()

## Check for invalid characters in the name
[void] (New-PsSpecNoun "Test!@#---Noun" TestNounDescription TestProject -Service $testService -ErrorAction SilentlyContinue)
AssertEquals 1 $error.Count "Should not be able to create a new project with invalid characters 2"
$error.Clear()

## Check Get-PsSpecNoun with bad noun name, no wildcards, and error
[void] (Get-PsSpecNoun "23afasdflkasjdflskajfdsf" "TestNounDescription" -Service $testService -ErrorAction SilentlyContinue)
AssertEquals 1 $error.Count "Should have generated an error for no-globbing noun name"
$error.Clear()

## Check Get-PsSpecNoun with bad definition, error
[void] (Get-PsSpecNoun "TestNoun" "Bad definition" -Service $testService -ErrorAction SilentlyContinue)
AssertEquals 1 $error.Count "Should have generated an error for no-globbing noun definition"
$error.Clear()

## Check Get-PsSpecNoun with globbed name, no error
$nouns = @(Get-PsSpecNoun "23afasdflkasjdflskajfdsf*" "Bad definition" -Service $testService -ErrorAction SilentlyContinue)
AssertEquals 0 $nouns.Count "Should not have generated an error for globbed noun name"
AssertEquals 0 $error.Count

## Check Get-PsSpecNoun with globbed description, no error
$nouns = @(Get-PsSpecNoun "23afasdflkasjdflskajfdsf" "Bad definition*" -Service $testService -ErrorAction SilentlyContinue)
AssertEquals 0 $nouns.Count "Should not have generated an error for globbed description"
AssertEquals 0 $error.Count

## Get a noun not used by a cmdlet
$nouns = @(Get-PsSpecNoun -Service $testService)
Assert ($nouns.Count -gt 5) "Should have got all the nouns back"

ClearSpecHistory
## Update noun description
Get-PsSpecNoun TestNounTwo -Service $testService | Set-PsSpecNoun -Definition "My new description" -Service $testService
$updatedNoun = @(Get-PsSpecNoun "TestNounTwo" -Service $testService)[0]
AssertEquals "TestNounTwo" $updatedNoun.Name
AssertEquals "My new description" $updatedNoun.Definition

## Verify that the history was updated
$project = Get-PsSpecProject TestProject -Service $testService
$history = @($project | Get-PsSpecHistory -ChangeType Project -Service $testService | ? { $_.ChangeType -eq "Noun" } )[0]
AssertEquals "My new description" $history.NewValue "Should have logged description change"

## Cannot update a shared noun

## Create the new cmdlet
[void] (New-PsSpecCmdlet -Snapin "FooSnapin" -Verb "Set" -Noun "SharedDependentNoun" -Project "TestProjectExistingProject" -Service $testService)
$cmdlet = Get-PsSpecCmdlet Set-SharedDependentNoun -ProjectName TestProjectExistingProject -Service $testService
AssertEquals "SharedDependentNoun" $cmdlet.Noun
AssertEquals 0 $error.Count "Should have worked with duplicate noun (shared)"

$error.Clear()

## Update the noun
$noun = Get-PsSpecNoun SharedDependentNoun -ProjectName TestProjectExistingProject -Service $testService
AssertEquals "This is a shared dependent noun that somebody will depend on" $noun.Definition
$noun | Set-PsSpecNoun -Definition "NewDefinition" -Service $testService
$noun = Get-PsSpecNoun SharedDependentNoun -ProjectName TestProjectExistingProject -Service $testService
AssertEquals "NewDefinition" $noun.Definition

## Have another project take a dependency
$dependentSql = "    EXEC NewCmdlet @snapin='FooSnapin',@verb='Get',@noun='SharedDependentNoun',@project='TestProjectExistingDependentProject',@shortDescription='Get a dependent noun',@longDescription='Get a dependent noun long desc.',@supportsShouldProcess=1,@notes='Some notes',@user='SECRETDOMAIN\dependentUser'"
[void] (& $sqlCommand $testDataSource $testDatabase $dependentSql)

## Get their cmdlet
$cmdlet = Get-PsSpecCmdlet Get-SharedDependentNoun -ProjectName TestProjectExistingDependentProject -Service $testService
AssertEquals "SharedDependentNoun" $cmdlet.Noun
AssertEquals 0 $error.Count "Should have worked with duplicate noun (shared)"
$error.Clear()

## Update the noun. Should fail.
$noun | Set-PsSpecNoun -Definition "This is a shared dependent noun that somebody will depend on" -Service $testService -ErrorAction SilentlyContinue
AssertEquals 1 $error.Count
$noun = Get-PsSpecNoun SharedDependentNoun -ProjectName TestProjectExistingProject -Service $testService
AssertEquals "NewDefinition" $noun.Definition
$error.Clear()

## Remove the noun. Should fail.
$noun | Remove-PsSpecNoun -Service $testService -Force -ErrorAction SilentlyContinue
AssertEquals 1 $error.Count
$nouns = @(Get-PsSpecNoun SharedDependentNoun -ProjectName TestProjectExistingProject -Service $testService)
AssertEquals 1 $nouns.Count
$error.Clear()

## Change case sensitivity on the noun.
get-psspecnoun -service $testService | where {$_.Name -eq "TestNoun"} | Set-PsSpecNoun -Name "testnoun" -Def "testnoundescription" -service $testService
$noun = Get-PsSpecnoun -ser $testService | where {$_.Name -eq "testnoun"}
$Nouncomparision = [String]::Compare($noun.Name,"testnoun",$False)
AssertEquals 0 $Nouncomparision "Case sensitivity is broken for noun name"
$Definitioncomparision = [String]::Compare($noun.Definition,"testnoundescription",$False)
AssertEquals 0 $Definitioncomparision "Case sensitivity is broken for noun definition"

## See that we can get all verbs
$verbs = Get-PsSpecVerb -Service $testService
Assert ($verbs.Count -ge 55) "There should be 55 or more verbs."

## See that we can get a specific verb
$getVerb = Get-PsSpecVerb Get -Service $testService
AssertEquals "Common" $getVerb.Type "Failed to get type property"
AssertEquals "Get" $getVerb.Name "Failed to get name property"
Assert ($getVerb.Definition.Length -gt 0) "Failed to get definition property"
Assert ($getVerb.Comments -match "Search")  "Failed to get commonparameters property"
Assert ($getVerb.Obsoletes.Length -gt 0) "Failed to get obsoletes property"
AssertEquals "Set" $getVerb.Pair "Failed to get pair property"

## Clean-up
Get-PsSpecNoun "TestNoun*" -Service $testService | Remove-PsSpecNoun -Service $testService -Force
$error.Clear()

## Create a valid project and noun for the cmdlet
[void] (New-PsSpecNoun TestNoun TestNounDescription TestProject -Service $testService)
[void] (New-PsSpecNoun TestNounTwo TestNoun2Description TestProject -Service $testService)

## Cmdlet with invalid verb
[void] (New-PsSpecCmdlet -Snapin "FooSnapin" -Verb "DoSomethingTo" -Noun "TestNoun" -Project "TestProject" -Service $testService -ea SilentlyContinue)
AssertEquals 1 $error.Count "Should have failed with invalid verb"
$error.Clear()

## Cmdlet with invalid noun
[void] (New-PsSpecCmdlet -Snapin "FooSnapin" -Verb "Get" -Noun "TestNounThatDoesntExist" -Project "TestProject" -Service $testService -ea SilentlyContinue)
AssertEquals 1 $error.Count "Should have failed with invalid noun"
$error.Clear()

## Cmdlet with invalid project
[void] (New-PsSpecCmdlet -Snapin "FooSnapin" -Verb "Get" -Noun "TestNoun" -Project "TestProjectThatDoesntExist" -Service $testService -ea SilentlyContinue)
AssertEquals 1 $error.Count "Should have failed with invalid project"
$error.Clear()

ClearSpecHistory

## Cmdlet with valid project and noun

$helpExample1 = New-Object Microsoft.PowerShell.CmdletManagement.PsSpecHelpExample
$helpExample1.Command = "Get-Process"
$helpExample1.Output = "... Processes ..."
$helpExample1.Description = "This command outputs some processes."

$helpExample2 = New-Object Microsoft.PowerShell.CmdletManagement.PsSpecHelpExample
$helpExample2.Command = "Get-Process2"
$helpExample2.Output = "... Processes ...2"
$helpExample2.Description = "This command outputs some processes.2"

$cmdlet = New-PsSpecCmdlet -Snapin "FooSnapin" -Verb "Get" -Noun "TestNoun" -ProjectName "TestProject" `
    -TeamMembers "Me, You" -ShortDescription "Short Description" `
    -LongDescription "Long Description" -SupportsShouldProcess -Notes "These are my notes" `
    -SpecExamples "Spec examples" -HelpExamples $helpExample1,$helpExample2 -OutputObject "System.String" -OutputObjectDescription "Description" `
    -RelatedTo "Set-TestNoun" -DefaultParameterSetName "DefaultParameterSet" -Custom1 "Custom 1" -Custom2 "Custom 2" `
    -Custom3 "Custom 3" -Custom4 "Custom 4" -Status "In Review" -HelpStatus "Not Started" -HelpShortDescription "Help Short Description" `
    -HelpLongDescription "Help Long Description" -InputObject "Input Object" `
    -HelpInputObjectDescription "Help Input Type Description" -HelpOutputObjectDescription "Help Return Type Description" `
    -HelpAdditionalNotes "Help Additional Notes" -Service $testService
AssertEquals "FooSnapin" $cmdlet.Snapin
AssertEquals "Get" $cmdlet.Verb
AssertEquals "TestNoun" $cmdlet.Noun
AssertEquals "TestProject" $cmdlet.ProjectName
AssertEquals "Me, You" $cmdlet.TeamMembers
AssertEquals "Short Description" $cmdlet.ShortDescription
AssertEquals "Long Description" $cmdlet.LongDescription
AssertEquals $true $cmdlet.SupportsShouldProcess
AssertEquals "These are my notes" $cmdlet.Notes
AssertEquals "Spec examples" $cmdlet.SpecExamples

AssertEquals "Get-Process" $cmdlet.HelpExamples[0].Command
AssertEquals "... Processes ..." $cmdlet.HelpExamples[0].Output
AssertEquals "This command outputs some processes." $cmdlet.HelpExamples[0].Description

AssertEquals "Get-Process2" $cmdlet.HelpExamples[1].Command
AssertEquals "... Processes ...2" $cmdlet.HelpExamples[1].Output
AssertEquals "This command outputs some processes.2" $cmdlet.HelpExamples[1].Description

AssertEquals "System.String" $cmdlet.OutputObject
AssertEquals "Description" $cmdlet.OutputObjectDescription
AssertEquals "Set-TestNoun" $cmdlet.RelatedTo
AssertEquals "DefaultParameterSet" $cmdlet.DefaultParameterSetName
AssertEquals "Custom 1" $cmdlet.Custom1
AssertEquals "Custom 2" $cmdlet.Custom2
AssertEquals "Custom 3" $cmdlet.Custom3
AssertEquals "Custom 4" $cmdlet.Custom4
AssertEquals "In Review" $cmdlet.Status
AssertEquals "Not Started" $cmdlet.HelpStatus
AssertEquals "Help Short Description" $cmdlet.HelpShortDescription
AssertEquals "Help Long Description" $cmdlet.HelpLongDescription
AssertEquals "Input Object" $cmdlet.InputObject
AssertEquals "Help Input Type Description" $cmdlet.HelpInputObjectDescription
AssertEquals "Help Return Type Description" $cmdlet.HelpOutputObjectDescription
AssertEquals "Help Additional Notes" $cmdlet.HelpAdditionalNotes
Assert ($cmdlet.Id -gt 0) "Cmdlet should have an ID"

AssertEquals 0 $error.Count "Create a valid cmdlet"
$error.Clear()

$history = @($cmdlet | Get-PsSpecHistory -ChangeType Cmdlet -Service $testService )
AssertEquals 29 $history.Count

$project = Get-PsSpecProject "TestProject" -Service $testService
$history = @($project | Get-PsSpecHistory -ChangeType Project -Service $testService  | ? { $_.CmdletName -eq "Get-TestNoun" })
AssertEquals 1 $history.Count

## Test cmdlet equality method
$compareCmdlet = $cmdlet.Clone()

Assert $cmdlet.Equals($compareCmdlet) "Cmdlet should start off equal"

foreach($property in $compareCmdlet.PsObject.Properties)
{
    $backupValue = $property.Value
    $compareCmdlet.$($property.Name) = $null
    Assert (-not $cmdlet.Equals($compareCmdlet)) "Change to $($property.Name) should have changed equality"
    $compareCmdlet.$($property.Name) = $backupValue
    Assert $cmdlet.Equals($compareCmdlet) "Restore to $($property.Name) should have restored equality"
}

ClearSpecHistory

## Add a new help example, update an old one, and delete an old one
$helpExample3 = New-Object Microsoft.PowerShell.CmdletManagement.PsSpecHelpExample
$helpExample3.Command = "Invoke-MyProcess"
$helpExample3.Output = "... Does some stuff"
$helpExample3.Description = "This command does other stuff"

$newExamples = $cmdlet.HelpExamples[0],$helpExample3
$newExamples[0].Command = "Get-Process3"

## Update a cmdlet
$cmdlet.Snapin = "FooSnapin2"
$cmdlet.Verb = "Set"
$cmdlet.Noun = "TestNounTwo"
$cmdlet.TeamMembers = "You, I"
$cmdlet.ShortDescription = "Short Description 2"
$cmdlet.LongDescription = "Long Description 2"
$cmdlet.SupportsShouldProcess = $false
$cmdlet.Notes = "More random notes"
$cmdlet.SpecExamples = "More random examples"
$cmdlet.HelpExamples = $newExamples
$cmdlet.OutputObject = "ExchangeString"
$cmdlet.OutputObjectDescription = "Exchange Description"
$cmdlet.RelatedTo = "Update-TestNoun"
$cmdlet.DefaultParameterSetName = "DefaultParameterSet2" 
$cmdlet.Custom1 = "Custom 12" 
$cmdlet.Custom2 = "Custom 22" 
$cmdlet.Custom3 = "Custom 32" 
$cmdlet.Custom4 = "Custom 42" 
$cmdlet.Status = "In Review2" 
$cmdlet.HelpStatus = "Not Started2" 
$cmdlet.HelpShortDescription = "Help Short Description2" 
$cmdlet.HelpLongDescription = "Help Long Description2" 
$cmdlet.InputObject = "Input Object2" 
$cmdlet.HelpInputObjectDescription = "Help Input Type Description2" 
$cmdlet.HelpOutputObjectDescription = "Help Return Type Description2" 
$cmdlet.HelpAdditionalNotes = "Help Additional Notes2" 

$cmdlet | Set-PsSpecCmdlet -Service $testService

## Verify that the history was updated
$history = @($cmdlet | Get-PsSpecHistory -ChangeType Cmdlet -Service $testService )
AssertEquals 30 $history.Count "Should have made 30 changes"

$cmdlet = Get-PsSpecCmdlet "Set-TestNounTwo" -Service $testService
AssertEquals "FooSnapin2" $cmdlet.Snapin
AssertEquals "Set" $cmdlet.Verb
AssertEquals "TestNounTwo" $cmdlet.Noun
AssertEquals "TestProject" $cmdlet.ProjectName
AssertEquals "You, I" $cmdlet.TeamMembers
AssertEquals "Short Description 2" $cmdlet.ShortDescription
AssertEquals "Long Description 2" $cmdlet.LongDescription
AssertEquals $false $cmdlet.SupportsShouldProcess
AssertEquals "More random notes" $cmdlet.Notes
AssertEquals "More random examples" $cmdlet.SpecExamples

AssertEquals "Get-Process3" $cmdlet.HelpExamples[0].Command
AssertEquals "... Processes ..." $cmdlet.HelpExamples[0].Output
AssertEquals "This command outputs some processes." $cmdlet.HelpExamples[0].Description

AssertEquals "Invoke-MyProcess" $cmdlet.HelpExamples[1].Command
AssertEquals "... Does some stuff" $cmdlet.HelpExamples[1].Output
AssertEquals "This command does other stuff" $cmdlet.HelpExamples[1].Description

AssertEquals "ExchangeString" $cmdlet.OutputObject
AssertEquals "Exchange Description" $cmdlet.OutputObjectDescription
AssertEquals "Update-TestNoun" $cmdlet.RelatedTo
AssertEquals "DefaultParameterSet2" $cmdlet.DefaultParameterSetName
AssertEquals "Custom 12" $cmdlet.Custom1
AssertEquals "Custom 22" $cmdlet.Custom2
AssertEquals "Custom 32" $cmdlet.Custom3
AssertEquals "Custom 42" $cmdlet.Custom4
AssertEquals "In Review2" $cmdlet.Status
AssertEquals "Not Started2" $cmdlet.HelpStatus
AssertEquals "Help Short Description2" $cmdlet.HelpShortDescription
AssertEquals "Help Long Description2" $cmdlet.HelpLongDescription
AssertEquals "Input Object2" $cmdlet.InputObject
AssertEquals "Help Input Type Description2" $cmdlet.HelpInputObjectDescription
AssertEquals "Help Return Type Description2" $cmdlet.HelpOutputObjectDescription
AssertEquals "Help Additional Notes2" $cmdlet.HelpAdditionalNotes

AssertEquals 0 $error.Count "Update a cmdlet"
$error.Clear()

$cmdlets = @(Get-PsSpecCmdlet "Get-TestNoun*" -Service $testService)
AssertEquals 0 $cmdlets.Count "Should have renamed cmdlet."

## Revert the cmdlet
$cmdlet.Snapin = "FooSnapin"
$cmdlet.Verb = "Get"
$cmdlet.Noun = "TestNoun"
$cmdlet.ShortDescription = "Short Description"
$cmdlet.LongDescription = "Long Description"
$cmdlet.SupportsShouldProcess = $true
$cmdlet.Notes = "These are my notes"
$cmdlet.SpecExamples = "More random examples"
$cmdlet.OutputObject = "ExchangeString"
$cmdlet.OutputObjectDescription = "Exchange Description"
$cmdlet.RelatedTo = "Set-TestNoun"
$cmdlet | Set-PsSpecCmdlet -Service $testService

## Update a noun, cmdlets should be updated, too
$cmdlet = Get-PsSpecCmdlet Get-TestNoun -ProjectName TestProject -Service $testService
AssertEquals "TestNoun" $cmdlet.Noun
$noun = Get-PsSpecNoun TestNoun -ProjectName TestProject -Service $testService
$noun | Set-PsSpecNoun -Name TestNounThree -Service $testService
$cmdlet = Get-PsSpecCmdlet Get-TestNounThree -ProjectName TestProject -Service $testService

AssertEquals "TestNounThree" $cmdlet.Noun
$noun | Set-PsSpecNoun -Name TestNoun  -Service $testService

## Get-PsSpecCmdlet with cmdlet name wildcard
$cmdlets = @(Get-PsSpecCmdlet "Get-Test*" -Service $testService)
AssertEquals 1 $cmdlets.Count

## Get-PsSpecCmdlet with project wildcard (exists)
$cmdlets = @(Get-PsSpecCmdlet "Get-TestNoun" -ProjectName "Test*" -Service $testService)
AssertEquals 1 $cmdlets.Count

## Get-PsSpecCmdlet with project wildcard (exists)
$cmdlets = @(Get-PsSpecCmdlet "Get-TestNoun" -ProjectName "TestProject" -Service $testService)
AssertEquals 1 $cmdlets.Count  "Should have 1 cmdlet"

## Get-PsSpecCmdlet with project wildcard (does not exist)
$cmdlets = @(Get-PsSpecCmdlet "Get-TestNoun" -ProjectName "Boo*" -Service $testService)
AssertEquals 0 $cmdlets.Count "Should have no cmdlets"

## Get-PsSpecCmdlet with missing cmdlet, no wildcard, generates error
$cmdlets = @(Get-PsSpecCmdlet "Get-MissingCmdlet" -ProjectName "MissingProject" -Service $testService -ErrorAction SilentlyContinue)
AssertEquals 1 $error.Count "Should have generated error on non-globbed cmdlet get"
$error.Clear()

## Add a minimal parameter
Add-PsSpecCmdletParameter -ProjectName "TestProject" -CmdletName "Get-TestNoun" -Name "TestParameter" -Type "String" -Service $testService
AssertEquals 0 $error.Count "Create a minimal parameter"
$error.Clear()

## Test the parameter equality method
$parameter = Get-PsSpecCmdletParameter -ProjectName "TestProject" -CmdletName "Get-TestNoun" -Name "TestParameter" -Service $testService
$parameterSetEntry = $parameter | Get-PsSpecCmdletParameterSetEntry -Service $testService

$parameter.Id = 10
$parameter.ProjectName = "Test"
$parameter.CmdletName = "TestCmdlet"
$parameter.Name = "Name"
$parameter.Type = "Type"
$parameter.Description = "Description"
$parameter.Alias = "Test"
$parameter.AllowGlobbing = $true
$parameter.AllowMultiple = $true
$parameter.IsDynamic = $true
$parameter.AllowEmptyCollection = $true
$parameter.AllowEmptyString = $true
$parameter.AllowNull = $true
$parameter.ValidateCount = 1,10
$parameter.ValidateNotNull = $true
$parameter.ValidateNotNullOrEmpty = $true
$parameter.ValidateRange = 1,10
$parameter.ValidateSet = "a-z"
$parameter.ValidateLength = 1,10
$parameter.ValidatePattern = "testpattern"
$parameter.Notes = "Notes"
$parameter.DefaultValue = "Default"
$parameter.Custom1 = "Custom1"
$parameter.Custom2 = "Custom2"
$parameter.Custom3 = "Custom3"
$parameter.Custom4 = "Custom4"
$parameter.HelpDescription = "Help!"

$compareParameter = $parameter.Clone()

Assert $parameter.Equals($compareParameter) "Parameter should start off equal"

foreach($property in $compareParameter.PsObject.Properties)
{
    $backupValue = $property.Value

    if($property.TypeNameOfValue -eq "System.Boolean")
    {
        $compareParameter.$($property.Name) = (-not $backupValue)
    }
    else
    {
        $compareParameter.$($property.Name) = $null
    }

    Assert (-not $parameter.Equals($compareParameter)) "Change to $($property.Name) should have changed parameter equality"
    $compareParameter.$($property.Name) = $backupValue
    Assert $parameter.Equals($compareParameter) "Restore to $($property.Name) should have restored parameter equality"
}

## Test the parameter set entry equality method
$parameterSetEntry.Id = 10
$parameterSetEntry.ProjectName = "TestProject"
$parameterSetEntry.CmdletName = "TestCmdlet"
$parameterSetEntry.ParameterName = "TestParameter"
$parameterSetEntry.ParameterSetName = "Parameter Set"
$parameterSetEntry.ProjectName = "Test"
$parameterSetEntry.Mandatory = $true
$parameterSetEntry.Position = 1
$parameterSetEntry.ValueFromPipeline = $true
$parameterSetEntry.ValueFromPipelineByPropertyName = $true
$parameterSetEntry.ValueFromRemainingArguments = $true
$parameterSetEntry.HelpMessage = "Help!"
$parameterSetEntry.HelpMessageBaseName = "Help! Base"
$parameterSetEntry.HelpMessageResourceId = "Help! Id"

$compareParameterSetEntry = $parameterSetEntry.Clone()

Assert $parameterSetEntry.Equals($compareParameterSetEntry) "Parameter set entry should start off equal"

foreach($property in $compareParameterSetEntry.PsObject.Properties)
{
    $backupValue = $property.Value

    if($property.TypeNameOfValue -eq "System.Boolean")
    {
        $compareParameterSetEntry.$($property.Name) = (-not $backupValue)
    }
    else
    {
        $compareParameterSetEntry.$($property.Name) = $null
    }

    Assert (-not $parameterSetEntry.Equals($compareParameterSetEntry)) "Change to $($property.Name) should have changed parameter set entry  equality"
    $compareParameterSetEntry.$($property.Name) = $backupValue
    Assert $parameterSetEntry.Equals($compareParameterSetEntry) "Restore to $($property.Name) should have restored parameter set entry equality"
}


## Add a parameter with a long type name
Add-PsSpecCmdletParameter -ProjectName "TestProject" -CmdletName "Get-TestNoun" -Name "TestParameterLong" -Type ("A"*500) -Service $testService
AssertEquals 0 $error.Count "Create a parameter with long type name"
$error.Clear()

## Add a parameter with an invalid name name
Add-PsSpecCmdletParameter -ProjectName "TestProject" -CmdletName "Get-TestNoun" -Name "Test ParameterLong" -Type String -ErrorAction SilentlyContinue -Service $testService
AssertEquals 1 $error.Count "Should have created an error"
$error.Clear()

ClearSpecHistory

## Add a complete parameter
Add-PsSpecCmdletParameter -ProjectName "TestProject" -CmdletName "Get-TestNoun" -Name "TestCompleteParameter" -Type "String" `
    -Alias Alias1,Alias2 -AllowGlobbing $true -AllowMultiple $true -Dynamic $true -AllowEmptyCollection $true `
    -AllowEmptyString $true -AllowNull $true -ValidateCount 1,10 -ValidateNotNull $false -ValidateNotNullOrEmpty $true `
    -ValidateRange 1,10 -ValidatePattern myPattern -Notes Hello -DefaultValue Test -Custom1 Custom1 -Custom2 Custom2 `
    -Custom3 Custom3 -Custom4 Custom4 -HelpDescription HelpDescription -Service $testService
$parameter = Get-PsSpecCmdletParameter -ProjectName "TestProject" -CmdletName "Get-TestNoun" -Name "TestCompleteParameter" -Service $testService 
AssertEquals "String" $parameter.Type  "Parameter type"
AssertArrayEquals Alias1,Alias2 $parameter.Alias "Parameter alias"
AssertEquals $true  $parameter.AllowGlobbing "AllowGlobbing"
AssertEquals $true $parameter.AllowMultiple "Parameter AllowMultiple"
AssertEquals $true $parameter.IsDynamic "Parameter Dynamic"
AssertEquals $true $parameter.AllowEmptyCollection "Parameter AllowEmptyCollection"
AssertEquals $true $parameter.AllowEmptyString "Parameter AllowEmptyString"
AssertEquals $true $parameter.AllowNull "Parameter AllowNull"
AssertArrayEquals 1,10 $parameter.ValidateCount "Parameter ValidateCount"
AssertEquals $false $parameter.ValidateNotNull "Parameter ValidateNotNull"
AssertEquals $true $parameter.ValidateNotNullOrEmpty "Parameter ValidateNotNullOrEmpty"
AssertArrayEquals 1,10 $parameter.ValidateRange "Parameter ValidateRange"
AssertEquals myPattern $parameter.ValidatePattern "Parameter ValidatePattern"
AssertEquals Hello $parameter.Notes "Parameter Notes"
AssertEquals Test $parameter.DefaultValue "Parameter DefaultValue"
AssertEquals Custom1 $parameter.Custom1 "Parameter Custom1"
AssertEquals Custom2 $parameter.Custom2 "Parameter Custom2"
AssertEquals Custom3 $parameter.Custom3 "Parameter Custom3"
AssertEquals Custom4 $parameter.Custom4 "Parameter Custom4"
AssertEquals HelpDescription $parameter.HelpDescription "Parameter HelpDescription"
AssertEquals 0 $error.Count "Create a complete parameter"
$error.Clear()

## Verify the history
## Verify that the history was updated
$history = @($cmdlet | Get-PsSpecHistory -ChangeType Cmdlet -Service $testService | ? { $_.ChangeType -eq "Cmdlet"} )
AssertEquals 1 $history.Count "Should have added 1 history entry"

$history = @($cmdlet | Get-PsSpecHistory -ChangeType Cmdlet -Service $testService | ? { $_.ChangeType -eq "CmdletParameter"} )
AssertEquals 19 $history.Count "Should have added 19 history entries"

$parameter = Get-PsSpecCmdletParameter -ProjectName "TestProject" -CmdletName "Get-TestNoun" -Name "TestParameterLong" -Service $testService
AssertEquals ("A"*500) $parameter.Type "Long ParameterType"

$parameters = @(Get-PsSpecCmdlet -Service $testService | Get-PsSpecCmdletParameter -Service $testService)
Assert ($parameters.Count -gt 0) "Should have piped to Get-PsSpecCmdletParameter"

## Get by name, type, description
$newParameters = @($parameters | Get-PsSpecCmdletParameter -Service $testService)
AssertEquals $parameters.count $newParameters.Count "Should have piped parameters to parameters"

## Should not be able to create dupe
Add-PsSpecCmdletParameter -ProjectName "TestProject" -CmdletName "Get-TestNoun" -Name "TestParameter" -Type "String" -Service $testService -ErrorAction SilentlyContinue
AssertEquals 1 $error.Count "Create a duplicate parameter"
$error.Clear()

$parameter = Get-PsSpecCmdletParameter -ProjectName "TestProject" -Name "TestParameter" -CmdletName "Get-TestNoun" -Service $testService
Assertequals "TestParameter" $parameter.Name "ParameterName"
AssertEquals "String" $parameter.Type "ParameterType"
AssertEquals $null $parameter.Description "Description"
AssertEquals $null $parameter.Alias "Alias"
AssertEquals $false $parameter.AllowGlobbing "AllowGlobbing"
AssertEquals $false $parameter.AllowMultiple "AllowMultiple"
AssertEquals $false $parameter.IsDynamic "Dynamic"
AssertEquals $false $parameter.AllowEmptyCollection "AllowEmptyCollection"
AssertEquals $false $parameter.AllowEmptyString "AllowEmptyString"
AssertEquals $false $parameter.AllowNull "AllowNull"
AssertEquals $null $parameter.ValidateCount "ValidateCount"
AssertEquals $true $parameter.ValidateNotNull "ValidateNotNull"
AssertEquals $true $parameter.ValidateNotNullOrEmpty "ValidateNotNullOrEmpty"
AssertEquals $null $parameter.ValidateRange "ValidateRange"
AssertEquals $null $parameter.ValidateSet "ValidateSet"
AssertEquals $null $parameter.ValidateLength "ValidateLength"
AssertEquals $null $parameter.ValidatePattern "ValidatePattern"
AssertEquals $null $parameter.Notes "Note"
AssertEquals $null $parameter.DefaultValue "Parameter DefaultValue"
AssertEquals $null $parameter.Custom1 "Parameter Custom1"
AssertEquals $null $parameter.Custom2 "Parameter Custom2"
AssertEquals $null $parameter.Custom3 "Parameter Custom3"
AssertEquals $null $parameter.Custom4 "Parameter Custom4"
AssertEquals $null $parameter.HelpDescription "Parameter HelpDescription"

Assert ($parameter.Id -gt 0) "Parameter should have an ID"

AssertEquals 0 $error.Count "Create a cmdlet parameter"

$error.Clear()

ClearSpecHistory

## Update a parameter
$parameter | Set-PsSpecCmdletParameter `
    -Type Int `
    -Alias "Id","PID" `
    -Description "Some Description" `
    -AllowGlobbing:$true `
    -AllowMultiple:$true `
    -Dynamic:$true `
    -AllowEmptyCollection:$true `
    -AllowEmptyString:$true `
    -AllowNull:$true `
    -ValidateCount 1,10 `
    -ValidateNotNull:$false `
    -ValidateNotNullOrEmpty:$false `
    -ValidateRange 0,99999 `
    -ValidateSet "These","Will","Not","Be","Used" `
    -ValidateLength 1,500 `
    -ValidatePattern "foo.*[a-zA-Z0-9]*" `
    -Notes "This is a note about the parameter" `
    -DefaultValue "DefaultValue" `
    -Custom1 "Custom1" `
    -Custom2 "Custom2" `
    -Custom3 "Custom3" `
    -Custom4 "Custom4" `
    -HelpDescription "HelpDescription" `
    -ServiceUri $testService

## Verify that the history was updated
$cmdlet = Get-PsSpecCmdlet "Get-TestNoun" -Service $testService
$history = @($cmdlet | Get-PsSpecHistory -ChangeType Cmdlet -Service $testService | ? { $_.ChangeType -eq "CmdletParameter"} )
AssertEquals 23 $history.Count "Should have added 23 history entries"

$parameter = Get-PsSpecCmdletParameter -ProjectName "TestProject" -Name "TestParameter" -CmdletName "Get-TestNoun" -Service $testService

## Validate the update
AssertEquals "TestParameter" $parameter.Name
AssertEquals "Int" $parameter.Type
AssertArrayEquals ("Id","PID") $parameter.Alias "Alias"
AssertEquals "Some Description" $parameter.Description "Description"
AssertEquals $true $parameter.AllowGlobbing "AllowGlobbing"
AssertEquals $true $parameter.AllowMultiple "AllowMultiple"
AssertEquals $true $parameter.IsDynamic "Dynamic"
AssertEquals $true $parameter.AllowEmptyCollection "AllowEmptyCollection"
AssertEquals $true $parameter.AllowEmptyString "AllowEmptyString"
AssertEquals $true $parameter.AllowNull "AllowNull"
AssertArrayEquals (1,10) $parameter.ValidateCount "ValidateCount"
AssertEquals $false $parameter.ValidateNotNull "ValidateNotNull"
AssertEquals $false $parameter.ValidateNotNullOrEmpty "ValidateNotNullOrEmpty"
AssertArrayEquals (0,99999) $parameter.ValidateRange "ValidateRange"
AssertArrayEquals ("These","Will","Not","Be","Used") $parameter.ValidateSet "ValidateSet"
AssertArrayEquals (1,500) $parameter.ValidateLength "ValidateLength"
AssertEquals "foo.*[a-zA-Z0-9]*" $parameter.ValidatePattern "ValidatePattern"
AssertEquals "This is a note about the parameter" $parameter.Notes "Note"
AssertEquals DefaultValue $parameter.DefaultValue "Updated Parameter DefaultValue"
AssertEquals Custom1 $parameter.Custom1 "Updated Parameter Custom1"
AssertEquals Custom2 $parameter.Custom2 "Updated Parameter Custom2"
AssertEquals Custom3 $parameter.Custom3 "Updated Parameter Custom3"
AssertEquals Custom4 $parameter.Custom4 "Updated Parameter Custom4"
AssertEquals HelpDescription $parameter.HelpDescription "Updated Parameter HelpDescription"

AssertEquals 0 $error.Count "Update a cmdlet parameter"

$error.Clear()

## Verify that we can't update to an invalid name
$parameter | Set-PsSpecCmdletParameter -Name "Test ParameterLong" -ErrorAction SilentlyContinue -Service $testService
AssertEquals 1 $error.Count "Updating parameter should have created an error"
$error.Clear()

## Verify that a parameter set entry was added by default
$parameterSetEntry = Get-PsSpecCmdletParameterSetEntry -ProjectName "TestProject" -CmdletName "Get-TestNoun" -ParameterName "TestParameter" -Service $testService

AssertEquals "TestProject" $parameterSetEntry.ProjectName "ParameterSetEntry Project 1"
AssertEquals "Get-TestNoun" $parameterSetEntry.CmdletName "ParameterSetEntry Cmdlet"
AssertEquals "TestParameter" $parameterSetEntry.ParameterName "ParameterSetEntry ParameterName"
AssertEquals $null $parameterSetEntry.ParameterSetName "ParameterSetEntry ParameterSetName"
AssertEquals $false $parameterSetEntry.Mandatory "ParameterSetEntry Mandatory"
AssertEquals $null $parameterSetEntry.Position "ParameterSetEntry Position"
AssertEquals $false $parameterSetEntry.ValueFromPipeline "ParameterSetEntry ValueFromPipeline"
AssertEquals $false $parameterSetEntry.ValueFromPipelineByPropertyName "ParameterSetEntry ValueFromPipelineByPropertyName"
AssertEquals $false $parameterSetEntry.ValueFromRemainingArguments "ParameterSetEntry ValueFromRemainingArguments"
AssertEquals $null $parameterSetEntry.HelpMessage "ParameterSetEntry HelpMessage"
AssertEquals $null $parameterSetEntry.HelpMessageBaseName "ParameterSetEntry HelpMessageBaseName"
AssertEquals $null $parameterSetEntry.HelpMessageResourceId "ParameterSetEntry HelpMessageResourceId"
Assert ($parameterSetEntry.Id -gt 0) "Parameter Set Entry should have an ID"

ClearSpecHistory

## Update a parameter set entry
$parameterSetEntry | Set-PsSpecCmdletParameterSetEntry `
    -ParameterSetName "Hi!" `
    -Mandatory:$true `
    -Position 0 `
    -ValueFromPipeline:$true `
    -ValueFromPipelineByPropertyName:$true `
    -ValueFromRemainingArguments:$true `
    -HelpMessage "This is a help message" `
    -HelpMessageBaseName "SomeBaseName" `
    -HelpMessageResourceId "HELPMESSAGE_RESOURCE" `
    -Service $testService

$parameterSetEntry = Get-PsSpecCmdletParameterSetEntry -ProjectName "TestProject" -CmdletName "Get-TestNoun" -ParameterName "TestParameter" -Service $testService
AssertEquals "TestProject" $parameterSetEntry.ProjectName "ParameterSetEntry Project"
AssertEquals "Get-TestNoun" $parameterSetEntry.CmdletName "ParameterSetEntry Cmdlet"
AssertEquals "TestParameter" $parameterSetEntry.ParameterName "ParameterSetEntry ParameterName"
AssertEquals "Hi!" $parameterSetEntry.ParameterSetName "ParameterSetEntry ParameterSetName"
AssertEquals $true $parameterSetEntry.Mandatory "ParameterSetEntry Mandatory"
AssertEquals 0 $parameterSetEntry.Position "ParameterSetEntry Position"
AssertEquals $true $parameterSetEntry.ValueFromPipeline "ParameterSetEntry ValueFromPipeline"
AssertEquals $true $parameterSetEntry.ValueFromPipelineByPropertyName "ParameterSetEntry ValueFromPipelineByPropertyName"
AssertEquals $true $parameterSetEntry.ValueFromRemainingArguments "ParameterSetEntry ValueFromRemainingArguments"
AssertEquals "This is a help message" $parameterSetEntry.HelpMessage "ParameterSetEntry HelpMessage"
AssertEquals "SomeBaseName" $parameterSetEntry.HelpMessageBaseName "ParameterSetEntry HelpMessageBaseName"
AssertEquals "HELPMESSAGE_RESOURCE" $parameterSetEntry.HelpMessageResourceId "ParameterSetEntry HelpMessageResourceId"

## Verify that the history was updated
$cmdlet = Get-PsSpecCmdlet "Get-TestNoun" -Service $testService
$history = @($cmdlet | Get-PsSpecHistory -ChangeType Cmdlet -Service $testService | ? { $_.ChangeType -eq "ParameterSetEntry"} )
AssertEquals 9 $history.Count "Should have added 9 history entries"

## Verify that we can reset the position
$parameterSetEntry | Set-PsSpecCmdletParameterSetEntry -Position $null -Service $testService
$parameterSetEntry = Get-PsSpecCmdletParameterSetEntry -ProjectName "TestProject" -CmdletName "Get-TestNoun" -ParameterName "TestParameter" -Service $testService
AssertEquals $null $parameterSetEntry.Position "ParameterSetEntry updated Position"

ClearSpecHistory

## Add a new parameter set entry by pipeline
$parameterSetEntry = New-Object Microsoft.PowerShell.CmdletManagement.PsSpecCmdletParameterSetEntry
$parameterSetEntry.Id = -1
$parameterSetEntry.ProjectName = "TestProject"
$parameterSetEntry.CmdletName = "Get-TestNoun"
$parameterSetEntry.ParameterName = "TestParameter"
$parameterSetEntry.ParameterSetName = "FooSet2"
$parameterSetEntry.Mandatory = $true
$parameterSetEntry.Position = 2
$parameterSetEntry.ValueFromPipeline = $true
$parameterSetEntry.ValueFromPipelineByPropertyName = $false
$parameterSetEntry.ValueFromRemainingArguments = $true
$parameterSetEntry.HelpMessage = "ParameterSetEntry HelpMessage"
$parameterSetEntry.HelpMessageBaseName = "ParameterSetEntry HelpMessageBaseName"
$parameterSetEntry.HelpMessageResourceId = "ParameterSetEntry HelpMessageResourceId"
$parameterSetEntry | Add-PsSpecCmdletParameterSetEntry -Service $testService

## Verify that the history was updated
$history = @($cmdlet | Get-PsSpecHistory -ChangeType Cmdlet -Service $testService | ? { $_.ChangeType -eq "CmdletParameter"} )
AssertEquals 1 $history.Count "Should have added 1 history entries"

$history = @($cmdlet | Get-PsSpecHistory -ChangeType Cmdlet -Service $testService | ? { $_.ChangeType -eq "ParameterSetEntry"} )
AssertEquals 7 $history.Count "Should have added 7 history entries"

## Validate from pipeline
$parameterSetEntry = @(Get-PsSpecCmdletParameterSetEntry -ProjectName "TestProject" -CmdletName "Get-TestNoun" -ParameterName "TestParameter" -Service $testService | Sort Id)[-1]
AssertEquals "TestProject" $parameterSetEntry.ProjectName "ParameterPipeline ProjectName"
AssertEquals "Get-TestNoun" $parameterSetEntry.CmdletName "ParameterPipeline CmdletName"
AssertEquals "TestParameter" $parameterSetEntry.ParameterName "ParameterPipeline ParameterName"
AssertEquals "FooSet2" $parameterSetEntry.ParameterSetName "ParameterPipeline ParameterSetName"
AssertEquals $true $parameterSetEntry.Mandatory "ParameterPipeline Mandatory"
AssertEquals 2 $parameterSetEntry.Position "ParameterPipeline Position"
AssertEquals $true $parameterSetEntry.ValueFromPipeline "ParameterPipeline ValueFromPipeline"
AssertEquals $false $parameterSetEntry.ValueFromPipelineByPropertyName "ParameterPipeline ValueFromPipelineByPropertyName"
AssertEquals $true $parameterSetEntry.ValueFromRemainingArguments "ParameterPipeline ValueFromRemainingArguments"
AssertEquals "ParameterSetEntry HelpMessage" $parameterSetEntry.HelpMessage "ParameterPipeline HelpMessage"
AssertEquals "ParameterSetEntry HelpMessageBaseName" $parameterSetEntry.HelpMessageBaseName "ParameterPipeline BaseName"
AssertEquals "ParameterSetEntry HelpMessageResourceId" $parameterSetEntry.HelpMessageResourceId "ParameterPipeline ResourceId"

ClearSpecHistory

## Remove the parameter by pipeline
$entries = @(Get-PsSpecCmdletParameterSetEntry -ProjectName "TestProject" -CmdletName "Get-TestNoun" -ParameterName "TestParameter" -Service $testService)
AssertEquals 2 $entries.Count "Should have found 2 parameter set entries"
$parameterSetEntry | Remove-PsSpecCmdletParameterSetEntry -Service $testService

## Verify that the history was updated
$cmdlet = Get-PsSpecCmdlet "Get-TestNoun" -Service $testService
$history = @($cmdlet | Get-PsSpecHistory -ChangeType Cmdlet -Service $testService )[0]
Assert ($history.Id -gt 0) "Should have a history ID"
AssertEquals "CmdletParameter" $history.ChangeType
Assert ($history.LastUpdated -gt ([DateTime]::Now.AddMinutes(-1))) "Should have had a recent change time"

$project = Get-PsSpecProject TestProject -Service $testService
$parameter = Get-PsSpecCmdletParameter -ProjectName "TestProject" -CmdletName "Get-TestNoun" -Name "TestParameter" -Service $testService
AssertEquals $history.ProjectName "TestProject"
AssertEquals $username $history.ChangedBy
AssertEquals $project.Id $history.ProjectId
AssertEquals $project.Name $history.ProjectName
AssertEquals $cmdlet.Id $history.CmdletId
AssertEquals "$($cmdlet.Verb)-$($cmdlet.Noun)" $history.CmdletName
AssertEquals $parameter.Id $history.ParameterId
AssertEquals $parameter.Name $history.ParameterName
AssertEquals "Remove" $history.Action
AssertEquals "ParameterSetEntry" $history.PropertyName
AssertEquals $parameterSetEntry.Id $history.OldValue
AssertEquals "" $history.NewValue

## Verify history with an unlimited explicit range
$cmdlet = Get-PsSpecCmdlet "Get-TestNoun" -Service $testService
$history = @($cmdlet | Get-PsSpecHistory -ChangeType Cmdlet -From ([DateTime]::Minvalue) `
    -To ([DateTime]::MaxValue) -Service $testService )[0]
Assert ($history.Id -gt 0) "Should have a history ID"
AssertEquals "CmdletParameter" $history.ChangeType
Assert ($history.LastUpdated -gt ([DateTime]::Now.AddMinutes(-1))) "Should have had a recent change time"
$project = Get-PsSpecProject TestProject -Service $testService
$parameter = Get-PsSpecCmdletParameter -ProjectName "TestProject" -CmdletName "Get-TestNoun" -Name "TestParameter" -Service $testService
AssertEquals $history.ProjectName "TestProject"
AssertEquals $username $history.ChangedBy
AssertEquals $project.Id $history.ProjectId
AssertEquals $project.Name $history.ProjectName
AssertEquals $cmdlet.Id $history.CmdletId
AssertEquals "$($cmdlet.Verb)-$($cmdlet.Noun)" $history.CmdletName
AssertEquals $parameter.Id $history.ParameterId
AssertEquals $parameter.Name $history.ParameterName
AssertEquals "Remove" $history.Action
AssertEquals "ParameterSetEntry" $history.PropertyName
AssertEquals $parameterSetEntry.Id $history.OldValue
AssertEquals "" $history.NewValue

## Verify history with an restricted "from" explicit range
$cmdlet = Get-PsSpecCmdlet "Get-TestNoun" -Service $testService
$history = @($cmdlet | Get-PsSpecHistory -ChangeType Cmdlet -From ([DateTime]::Now.AddMinutes(-1)) `
    -Service $testService )[0]
Assert ($history.Id -gt 0) "Should have a history ID"
AssertEquals "CmdletParameter" $history.ChangeType
Assert ($history.LastUpdated -gt ([DateTime]::Now.AddMinutes(-1))) "Should have had a recent change time"
$project = Get-PsSpecProject TestProject -Service $testService
$parameter = Get-PsSpecCmdletParameter -ProjectName "TestProject" -CmdletName "Get-TestNoun" -Name "TestParameter" -Service $testService
AssertEquals $history.ProjectName "TestProject"
AssertEquals $username $history.ChangedBy
AssertEquals $project.Id $history.ProjectId
AssertEquals $project.Name $history.ProjectName
AssertEquals $cmdlet.Id $history.CmdletId
AssertEquals "$($cmdlet.Verb)-$($cmdlet.Noun)" $history.CmdletName
AssertEquals $parameter.Id $history.ParameterId
AssertEquals $parameter.Name $history.ParameterName
AssertEquals "Remove" $history.Action
AssertEquals "ParameterSetEntry" $history.PropertyName
AssertEquals $parameterSetEntry.Id $history.OldValue
AssertEquals "" $history.NewValue

## Verify history with an restricted "to" explicit range
$cmdlet = Get-PsSpecCmdlet "Get-TestNoun" -Service $testService
$history = @($cmdlet | Get-PsSpecHistory -ChangeType Cmdlet -To ([DateTime]::Now.AddMinutes(1)) `
    -Service $testService )[0]
Assert ($history.Id -gt 0) "Should have a history ID"
AssertEquals "CmdletParameter" $history.ChangeType
Assert ($history.LastUpdated -gt ([DateTime]::Now.AddMinutes(-1))) "Should have had a recent change time"
$project = Get-PsSpecProject TestProject -Service $testService
$parameter = Get-PsSpecCmdletParameter -ProjectName "TestProject" -CmdletName "Get-TestNoun" -Name "TestParameter" -Service $testService
AssertEquals $history.ProjectName "TestProject"
AssertEquals $username $history.ChangedBy
AssertEquals $project.Id $history.ProjectId
AssertEquals $project.Name $history.ProjectName
AssertEquals $cmdlet.Id $history.CmdletId
AssertEquals "$($cmdlet.Verb)-$($cmdlet.Noun)" $history.CmdletName
AssertEquals $parameter.Id $history.ParameterId
AssertEquals $parameter.Name $history.ParameterName
AssertEquals "Remove" $history.Action
AssertEquals "ParameterSetEntry" $history.PropertyName
AssertEquals $parameterSetEntry.Id $history.OldValue
AssertEquals "" $history.NewValue

## Verify absent history with a restricted date range
$cmdlet = Get-PsSpecCmdlet "Get-TestNoun" -Service $testService
$history = @($cmdlet | Get-PsSpecHistory -ChangeType Cmdlet -From ([DateTime]::Now.AddMinutes(1)) `
    -To ([DateTime]::Now.AddMinutes(2)) -Service $testService -EA SilentlyContinue)
AssertEquals 0 $history.Count
AssertEquals 1 $error.Count
$error.Clear()

## Verify absent history with a different change type
$cmdlet = Get-PsSpecCmdlet "Get-TestNoun" -Service $testService
$history = @($cmdlet | Get-PsSpecHistory -ChangeType Project -Service $testService )
AssertEquals 0 $history.Count
   
$entries = @(Get-PsSpecCmdletParameterSetEntry -ProjectName "TestProject" -CmdletName "Get-TestNoun" -ParameterName "TestParameter" -Service $testService)
AssertEquals 1 $entries.Count "Should have found 1 parameter set entry"

## Add with minimal set of parameters
Add-PsSpecCmdletParameterSetEntry -ProjectName "TestProject" -CmdletName "Get-TestNoun" -ParameterName "TestParameter" -ParameterSetName "FooSet" -Service $testService
$parameterSetEntry = @(Get-PsSpecCmdletParameterSetEntry -ProjectName "TestProject" -CmdletName "Get-TestNoun" -ParameterName "TestParameter" -Service $testService | Sort Id)[-1]
AssertEquals "TestProject" $parameterSetEntry.ProjectName "ParameterSetEntry Project 1"
AssertEquals "Get-TestNoun" $parameterSetEntry.CmdletName "ParameterSetEntry Cmdlet"
AssertEquals "TestParameter" $parameterSetEntry.ParameterName "ParameterSetEntry ParameterName"
AssertEquals "FooSet" $parameterSetEntry.ParameterSetName "ParameterSetEntry ParameterSetName"
AssertEquals $false $parameterSetEntry.Mandatory "ParameterSetEntry Mandatory"
AssertEquals $null $parameterSetEntry.Position "ParameterSetEntry Position"
AssertEquals $false $parameterSetEntry.ValueFromPipeline "ParameterSetEntry ValueFromPipeline"
AssertEquals $false $parameterSetEntry.ValueFromPipelineByPropertyName "ParameterSetEntry ValueFromPipelineByPropertyName"
AssertEquals $false $parameterSetEntry.ValueFromRemainingArguments "ParameterSetEntry ValueFromRemainingArguments"
AssertEquals $null $parameterSetEntry.HelpMessage "ParameterSetEntry HelpMessage"
AssertEquals $null $parameterSetEntry.HelpMessageBaseName "ParameterSetEntry HelpMessageBaseName"
AssertEquals $null $parameterSetEntry.HelpMessageResourceId "ParameterSetEntry HelpMessageResourceId"

## Update and verify
$parameterId = $parameterSetEntry.Id
$parameterSetEntry.ParameterSetName = "FooParamSet"
$parameterSetEntry.Position = 10
$parameterSetEntry | Set-PsSpecCmdletParameterSetEntry -Service $testService
$parameterSetEntry = Get-PsSpecCmdletParameterSetEntry -ProjectName "TestProject" -CmdletName "Get-TestNoun" -ParameterName "TestParameter" -Service $testService | ? { $_.Id -eq $parameterId }

AssertEquals "TestProject" $parameterSetEntry.ProjectName "ParameterSetEntry Project 1"
AssertEquals "Get-TestNoun" $parameterSetEntry.CmdletName "ParameterSetEntry Cmdlet"
AssertEquals "TestParameter" $parameterSetEntry.ParameterName "ParameterSetEntry ParameterName"
AssertEquals "FooParamSet" $parameterSetEntry.ParameterSetName "ParameterSetEntry ParameterSetName"
AssertEquals $false $parameterSetEntry.Mandatory "ParameterSetEntry Mandatory"
AssertEquals 10 $parameterSetEntry.Position "ParameterSetEntry Position"
AssertEquals $false $parameterSetEntry.ValueFromPipeline "ParameterSetEntry ValueFromPipeline"
AssertEquals $false $parameterSetEntry.ValueFromPipelineByPropertyName "ParameterSetEntry ValueFromPipelineByPropertyName"
AssertEquals $false $parameterSetEntry.ValueFromRemainingArguments "ParameterSetEntry ValueFromRemainingArguments"
AssertEquals $null $parameterSetEntry.HelpMessage "ParameterSetEntry HelpMessage"
AssertEquals $null $parameterSetEntry.HelpMessageBaseName "ParameterSetEntry HelpMessageBaseName"
AssertEquals $null $parameterSetEntry.HelpMessageResourceId "ParameterSetEntry HelpMessageResourceId"

## Verify that we can copy parameters as done in the UI
$groupEntryParameterName = "TestParameter"
$groupEntryType = "Int"
$groupEntryDescription = "Some Description"
[void] (New-PsSpecCmdlet -Snapin "FooSnapin" -ProjectName TestProject -Verb "Invoke" -Noun "TestNoun" -Service $testService)

## Step 1, copy the parameter
Get-PsSpecCmdletParameter -Name $groupEntryParameterName -Type $groupEntryType -Description $groupEntryDescription -Service $testService | 
    Select -First 1 | 
    Add-PsSpecCmdletParameter -ProjectName "TestProject" -CmdletName "Invoke-TestNoun" -Service $testService

$parameter = Get-PsSpecCmdletParameter -CmdletName "Invoke-TestNoun" -Name $groupEntryParameterName -Type $groupEntryType -Description $groupEntryDescription -Service $testService

AssertEquals "TestParameter" $parameter.Name
AssertEquals "Int" $parameter.Type
AssertArrayEquals ("Id","PID") $parameter.Alias "Alias"
AssertEquals $true $parameter.AllowGlobbing "AllowGlobbing"
AssertEquals $true $parameter.AllowMultiple "AllowMultiple"
AssertEquals $true $parameter.IsDynamic "Dynamic"
AssertEquals $true $parameter.AllowEmptyCollection "AllowEmptyCollection"
AssertEquals $true $parameter.AllowEmptyString "AllowEmptyString"
AssertEquals $true $parameter.AllowNull "AllowNull"
AssertArrayEquals (1,10) $parameter.ValidateCount "ValidateCount"
AssertEquals $false $parameter.ValidateNotNull "ValidateNotNull"
AssertEquals $false $parameter.ValidateNotNullOrEmpty "ValidateNotNullOrEmpty"
AssertArrayEquals (0,99999) $parameter.ValidateRange "ValidateRange"
AssertArrayEquals ("These","Will","Not","Be","Used") $parameter.ValidateSet "ValidateSet"
AssertArrayEquals (1,500) $parameter.ValidateLength "ValidateLength"
AssertEquals "foo.*[a-zA-Z0-9]*" $parameter.ValidatePattern "ValidatePattern"
AssertEquals "This is a note about the parameter" $parameter.Notes "Note"

## Step 2, delete the old parameter set entries
Get-PsSpecCmdletParameterSetEntry -ParameterName $groupEntryParameterName -ProjectName "TestProject" -CmdletName "Invoke-TestNoun" -Service $testService | 
    Remove-PsSpecCmdletParameterSetEntry -Service $testService

AssertEquals 0 @(Get-PsSpecCmdletParameterSetEntry -ParameterName $groupEntryParameterName -ProjectName "TestProject" -CmdletName "Invoke-TestNoun" -Service $testService).Count "Should have removed previous parameter set entries"

## Step 3, add the new parameter set entries
Get-PsSpecCmdletParameter -Name $groupEntryParameterName -Type $groupEntryType -Description $groupEntryDescription -Service $testService | 
    Select -First 1 | 
    Get-PsSpecCmdletParameterSetEntry -ParameterName $groupEntryParameterName -Service $testService |
    Add-PsSpecCmdletParameterSetEntry -ProjectName "TestProject" -CmdletName "Invoke-TestNoun" -Service $testService

$originalParameterSetEntries = @(Get-PsSpecCmdletParameterSetEntry -Cmdlet "Get-TestNoun" -ParameterName $groupEntryParameterName -Service $testService)
$newParameterSetEntries = @(Get-PsSpecCmdletParameterSetEntry -Cmdlet "Invoke-TestNoun" -ParameterName $groupEntryParameterName -Service $testService)

AssertEquals $originalParameterSetEntries.Count $newParameterSetEntries.Count "Should have the same number of parameter set entries"
for($counter = 0; $counter -lt $originalParameterSetEntries.Count; $counter++)
{
    $differences = @(Compare-Object @($originalParameterSetEntries[$counter].PsObject.Properties) `
        @($newParameterSetEntries[$counter].PsObject.Properties) -Prop Name,Value)
    AssertEquals 6 $differences.Count "Should have found 6 differences (id and cmdlet name and parameterId) on parameter $counter"
}


## Clone a cmdlet, as done in the UI
## Clones Get-TestNoun to Restore-TestNoun
$existingCmdlet = Get-PsSpecCmdlet Get-TestNoun -Service $testService
$cmdletName = "{0}-{1}" -f $existingCmdlet.Verb,$existingCmdlet.Noun
$parameters = $existingCmdlet | Get-PsSpecCmdletParameter -Service $testService
$parameterSetEntries = Get-PsSpecCmdletParameterSetEntry -CmdletName $cmdletName -Service $testService
$newCmdlet = $existingCmdlet | New-PsSpecCmdlet -Verb Restore -Noun TestNoun -Service $testService
$cmdletName = "{0}-{1}" -f $newCmdlet.Verb,$newCmdlet.Noun
$parameters | Add-PsSpecCmdletParameter -CmdletName $cmdletName -Service $testService
Get-PsSpecCmdletParameterSetEntry -CmdletName $cmdletName -Service $testService | Remove-PsSpecCmdletParameterSetEntry -Service $testService
$parameterSetEntries | Add-PsSpecCmdletParameterSetEntry -CmdletName $cmdletName -Service $testService

## Verify that the cmdlet details are the same
$cmdlet1 = Get-PsSpecCmdlet Get-TestNoun -Service $testService
$cmdlet2 = Get-PsSpecCmdlet Restore-TestNoun -Service $testService
$differences = @(Compare-Object @($cmdlet1.PsObject.Properties) @($cmdlet2.PsObject.Properties) -Prop Name,Value)
AssertEquals 4 $differences.Count "Should have found 4 differences (id and verb)"

## Verify that the parameters are the same
$parameters1 = $cmdlet1 | Get-PsSpecCmdletParameter -Service $testService
$parameters2 = $cmdlet2 | Get-PsSpecCmdletParameter -Service $testService
for($counter = 0; $counter -lt $parameters1.Count; $counter++)
{
    $differences = @(Compare-Object @($parameters1[$counter].PsObject.Properties) @($parameters2[$counter].PsObject.Properties) -Prop Name,Value)
    AssertEquals 4 $differences.Count "Should have found 4 differences (id and cmdlet name) on parameter $counter"
}

## Verify that the parameter set entries are the same
$parameterSetEntries1 = Get-PsSpecCmdletParameterSetEntry -CmdletName Get-TestNoun -Service $testService
$parameterSetEntries2 = Get-PsSpecCmdletParameterSetEntry -CmdletName Restore-TestNoun -Service $testService
for($counter = 0; $counter -lt $parameterSetEntries1.Count; $counter++)
{
    $differences = @(Compare-Object @($parameterSetEntries1[$counter].PsObject.Properties) @($parameterSetEntries2[$counter].PsObject.Properties) -Prop Name,Value)
    AssertEquals 6 $differences.Count "Should have found 6 differences (id and cmdlet name and parameterId) on parameter set entry $counter"
}

## Duplicate cmdlet, same project, should fail
[void] (New-PsSpecCmdlet -Snapin "FooSnapin" -Verb "Get" -Noun "TestNoun" -Project "TestProject" -Service $testService -ea SilentlyContinue)
AssertEquals 1 $error.Count "Should have failed with duplicate cmdlet information project"
$error.Clear()

## New cmdlet, restricted verb, wrong project, should fail
$cmdlet = New-PsSpecCmdlet -Snapin "FooSnapin" -Verb "Grant" -Noun "TestNoun" -Project "TestProject" -Service $testService -ea SilentlyContinue
AssertEquals 1 $error.Count "Should not be able to create a cmdlet with restricted verb"
$error.Clear()

## New cmdlet, restricted verb, exception granted, should work
$sql = @"
    DECLARE @projectId INT
    SET @projectId = (SELECT ProjectId FROM Project
                      WHERE Name = 'TestProject')

    INSERT INTO [VerbException]
           ([Name], [ProjectId])
    VALUES
           ('Grant', @projectId)
"@

[void] (& $sqlCommand $testDataSource $testDatabase $sql) 

$cmdlet = New-PsSpecCmdlet -Snapin "FooSnapin" -Verb "Grant" -Noun "TestNoun" -Project "TestProject" -Service $testService -ea SilentlyContinue
AssertEquals 0 $error.Count "Should be able to create a cmdlet with restricted verb (exclusion granted)"
$error.Clear()

## New cmdlet, restricted noun, same project, should work
$cmdlet = New-PsSpecCmdlet -Snapin "FooSnapin" -Verb "Set" -Noun "TestNoun" -Project "TestProject" -Service $testService -ea SilentlyContinue
AssertEquals 0 $error.Count "Should not have failed with new cmdlet in same project"
$error.Clear()

## New cmdlet, restricted noun (default), should fail
[void] (New-PsSpecCmdlet -Snapin "FooSnapin" -Verb "Get" -Noun "RestrictedNoun" -Project "TestProject" -Service $testService -ea SilentlyContinue)
AssertEquals 1 $error.Count "Should have failed rename with restricted cmdlet error"
$error.Clear()

## Should not be able to rename to a restricted noun
$cmdlet | Set-PsSpecCmdlet -Noun "RestrictedNoun" -Service $testService -ea SilentlyContinue
AssertEquals 1 $error.Count "Should have failed with restricted cmdlet error"
$error.Clear()

## Duplicate cmdlet, shared noun, should fail
[void] (New-PsSpecCmdlet -Snapin "FooSnapin" -Verb "Get" -Noun "SharedNoun" -Project "TestProject" -Service $testService -ea SilentlyContinue)
AssertEquals 1 $error.Count "Should have failed with duplicate cmdlet information project (shared)"
$error.Clear()

## New noun, shared noun, should work
[void] (New-PsSpecCmdlet -Snapin "FooSnapin" -Verb "Set" -Noun "SharedNoun" -Project "TestProject" -Service $testService -ea SilentlyContinue)
AssertEquals 0 $error.Count "Should have worked with duplicate noun (shared)"
$error.Clear()

## Duplicate cmdlet, common noun, should work
[void] (New-PsSpecCmdlet -Snapin "FooSnapin" -Verb "Get" -Noun "CommonNoun" -Project "TestProject" -Service $testService -ea SilentlyContinue)
AssertEquals 0 $error.Count "Should have worked with shared noun"
$error.Clear()

## Check Get-PsSpecNoun with invalid project name, causes error
$nouns = @(Get-PsSpecNoun "TestNoun" "TestNounDescription" "TestProjectFoo" -Service $testService -ErrorAction SilentlyContinue)
AssertEquals 1 $error.Count "Should have generated an error for no-globbing project name"
$error.Clear()

## Check Get-PsSpecNoun with valid project name, no error
$nouns = @(Get-PsSpecNoun "TestNoun" "TestNounDescription" "TestProject" -Service $testService -ErrorAction SilentlyContinue)
AssertEquals 1 $nouns.Count "Should not have generated an error for filtered project name"
AssertEquals 0 $error.Count

## Check Get-PsSpecNoun with globbed (but missing) project name, no error
$nouns = @(Get-PsSpecNoun "TestNoun" "TestNounDescription" "TestProjectFoo*" -Service $testService -ErrorAction SilentlyContinue)
AssertEquals 0 $nouns.Count "Should not have generated an error for globbed missing project name"
AssertEquals 0 $error.Count

## Fail to remove noun used by cmdlet
Get-PsSpecNoun "TestNoun*" -Service $testService | Remove-PsSpecNoun -Force -Service $testService -ea SilentlyContinue
AssertEquals 1 $error.Count "Should have failed with duplicate cmdlet information project (removal)"
$error.Clear()

ClearSpecHistory

## Remove a renamed noun
$noun = New-PsSpecNoun "TestNoun4" "TestNounDescription" "TestProject" -Service $testService
AssertEquals 1 @(Get-PsSpecNoun "TestNoun4*" -Service $testService).Count
AssertEquals 0 @(Get-PsSpecNoun "TestNoun5*" -Service $testService).Count
$noun | Set-PsSpecNoun -Name "TestNoun5" -Service $testService
AssertEquals 0 @(Get-PsSpecNoun "TestNoun4*" -Service $testService).Count
AssertEquals 1 @(Get-PsSpecNoun "TestNoun5*" -Service $testService).Count
$noun | Remove-PsSpecNoun -Force -Service $testService
AssertEquals 0 @(Get-PsSpecNoun "TestNoun4*" -Service $testService).Count
AssertEquals 0 @(Get-PsSpecNoun "TestNoun5*" -Service $testService).Count

## Verify that the noun history was updated
$project = Get-PsSpecProject TestProject -Service $testService
$history = @($project | Get-PsSpecHistory -ChangeType Project -Service $testService | ? { $_.PropertyName -eq "Noun"} )[0]
Assert ($history.Id -gt 0) "Should have a history ID"

ClearSpecHistory

## Should be able to remove a parameter
Remove-PsSpecCmdletParameter -ProjectName "TestProject" -CmdletName "Get-TestNoun" -Name "TestParameter" -Service $testService
AssertEquals 0 $error.Count
$error.Clear()

## Verify that the history was updated
$cmdlet = Get-PsSpecCmdlet "Get-TestNoun" -Service $testService
$history = @($cmdlet | Get-PsSpecHistory -ChangeType Cmdlet -Service $testService | ? { $_.ParameterName -eq "TestParameter"} )[0]
Assert ($history.Id -gt 0) "Should have a history ID"

## Should be able to remove a renamed parameter
Add-PsSpecCmdletParameter -ProjectName "TestProject" -CmdletName "Get-TestNoun" -Name "TestParameter" -Type "String" -Service $testService
$parameter = Get-PsSpecCmdletParameter -ProjectName "TestProject" -CmdletName "Get-TestNoun" -Name "TestParameter" -Service $testService
$parameter | Set-PsSpecCmdletParameter -Name "TestParameter2" -Service $testService
AssertEquals 0 @(Get-PsSpecCmdletParameter -ProjectName "TestProject" -CmdletName "Get-TestNoun" -Name "TestParameter" -Service $testService).Count "Should have renamed"
AssertEquals 1 @(Get-PsSpecCmdletParameter -ProjectName "TestProject" -CmdletName "Get-TestNoun" -Name "TestParameter2" -Service $testService).Count "Should have renamed 2"
$parameter | Remove-PsSpecCmdletParameter -Service $testService
AssertEquals 0 @(Get-PsSpecCmdletParameter -ProjectName "TestProject" -CmdletName "Get-TestNoun" -Name "TestParameter2" -Service $testService).Count "Should have renamed 2"

AssertEquals 0 $error.Count
$error.Clear()

## Re-add the parameter, so it gets cleaned up
Add-PsSpecCmdletParameter -ProjectName "TestProject" -CmdletName "Get-TestNoun" -Name "TestParameter" -Type "String" -Service $testService
AssertEquals 0 $error.Count
$error.Clear()

## Ensure the entry grouping returns no errors
$group = Get-PsSpecCmdletParameterGroupEntry -Service $testService
$total = ($group | Measure-Object -Sum Count).Sum
AssertEquals 7 $total "Group entries should have added to 7"
AssertEquals 0 $error.Count
$error.Clear()

## Ensure that cmdlet removal works
ClearSpecHistory

Remove-PsSpecCmdlet "Get-TestNoun" "TestProject" -Service $testService -Force
$cmdlet = Get-PsSpecCmdlet "Get-TestNoun" -Service $testService
AssertEquals $null $cmdlet

## Verify that the history was updated
$project = Get-PsSpecProject TestProject -Service $testService
$history = @($project | Get-PsSpecHistory -ChangeType Project -Service $testService | ? { $_.CmdletName -eq "Get-TestNoun"} )[0]
Assert ($history.Id -gt 0) "Should have a history ID"


## Ensure that we can remove a renamed cmdlet
$cmdlet = New-PsSpecCmdlet -Snapin "FooSnapin" -Verb "Get" -Noun "TestNoun" -ProjectName "TestProject" -Service $testService
$cmdlet | Set-PsSpecCmdlet -Verb "Stop" -Service $testService
AssertEquals 1 @(Get-PsSpecCmdlet -ProjectName TestProject -Name "Stop-TestNoun" -Service $testService).Count "Should have renamed cmdlet"
AssertEquals 0 @(Get-PsSpecCmdlet -ProjectName TestProject -Name "Get-TestNoun*" -Service $testService).Count "Should have renamed cmdlet"
$cmdlet | Remove-PsSpecCmdlet -Service $testService -Force
AssertEquals 0 @(Get-PsSpecCmdlet -ProjectName TestProject -Name "Stop-TestNoun*" -Service $testService).Count "Should have removed renamed cmdlet"

## Clean-up
## Remove-PsSpecCmdlet should kill parameters as well
$projectId = (Get-PsSpecProject TestProjectExistingDependentProject -Service $testService).Id
[void] (& $sqlCommand $testDataSource $testDatabase "EXEC RemoveProject '$projectId','SECRETDOMAIN\dependentUser'")

Get-PsSpecProject "TestProject*" -Service $testService | Remove-PsSpecProject -Service $testService -Force

ClearSpecHistory

## Verify we're at a clean slate
$projects = @(Get-PsSpecProject "TestProject*" -Service $testService)
AssertEquals 0 $projects.Count "Should have removed projects and dependencies."
